package org.dromara.oce.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.oce.config.JuLiangConfig;
import org.dromara.oce.config.JuLiangProperties;
import org.dromara.oce.domain.OceAdvertiserEverydayCost;
import org.dromara.oce.domain.OceAdvertiserReferralRelation;
import org.dromara.oce.domain.bo.OceAdvertiserReferralRelationBo;
import org.dromara.oce.domain.dto.GetAdvertiserInfo;
import org.dromara.oce.domain.vo.OceAdvertiserReferralRelationVo;
import org.dromara.oce.mapper.OceAdvertiserEverydayCostMapper;
import org.dromara.oce.mapper.OceAdvertiserReferralRelationMapper;
import org.dromara.oce.service.OceAdvertiserReferralRelationService;
import org.dromara.oce.service.remote.OceanEngineRemoteService;
import org.dromara.oce.service.inner.DsdjServeRemoteService;
import org.dromara.oce.utils.CommonConstants;
import org.dromara.oce.utils.DateTimeUtil;
import org.dromara.system.domain.SysDept;
import org.dromara.system.mapper.SysDeptMapper;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * 推广链接-广告主关联Service业务层处理
 *
 * @author Lion Li
 * @date 2024-12-24
 */
@RequiredArgsConstructor
@Service
public class OceAdvertiserReferralRelationServiceImpl extends ServiceImpl<OceAdvertiserReferralRelationMapper, OceAdvertiserReferralRelation> implements OceAdvertiserReferralRelationService {

    private final OceAdvertiserEverydayCostMapper oceAdvertiserEverydayCostMapper;
    private final SysDeptMapper deptMapper;
    private final OceanEngineRemoteService oceanEngineRemoteService;
    private final JuLiangConfig juLiangConfig;
    private final DsdjServeRemoteService dsdjServeRemoteService;

    /**
     * 查询推广链接-广告主关联
     *
     * @param advertiserReferralId 主键
     * @return 推广链接-广告主关联
     */
    @Override
    public OceAdvertiserReferralRelationVo queryById(Long advertiserReferralId) {
        return baseMapper.selectVoById(advertiserReferralId);
    }

    /**
     * 分页查询推广链接-广告主关联列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 推广链接-广告主关联分页列表
     */
    @Override
    public TableDataInfo<OceAdvertiserReferralRelationVo> queryPageList(OceAdvertiserReferralRelationBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OceAdvertiserReferralRelation> lqw = buildQueryWrapper(bo);
        Page<OceAdvertiserReferralRelationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的推广链接-广告主关联列表
     *
     * @param bo 查询条件
     * @return 推广链接-广告主关联列表
     */
    @Override
    public List<OceAdvertiserReferralRelationVo> queryList(OceAdvertiserReferralRelationBo bo) {
        LambdaQueryWrapper<OceAdvertiserReferralRelation> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OceAdvertiserReferralRelation> buildQueryWrapper(OceAdvertiserReferralRelationBo bo) {
        LambdaQueryWrapper<OceAdvertiserReferralRelation> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getThirdAdvertiserId()), OceAdvertiserReferralRelation::getThirdAdvertiserId, bo.getThirdAdvertiserId());
        lqw.like(StringUtils.isNotBlank(bo.getThirdAdvertiserName()), OceAdvertiserReferralRelation::getThirdAdvertiserName, bo.getThirdAdvertiserName());
        lqw.like(bo.getReferralLinkId() != null, OceAdvertiserReferralRelation::getReferralLinkId, bo.getReferralLinkId());
        lqw.eq(bo.getReferralLinkType() != null, OceAdvertiserReferralRelation::getReferralLinkType, bo.getReferralLinkType());
        lqw.eq(bo.getAppType() != null, OceAdvertiserReferralRelation::getAppType, bo.getAppType());
        lqw.eq(bo.getPullStatus() != null, OceAdvertiserReferralRelation::getPullStatus, bo.getPullStatus());
        lqw.like(StringUtils.isNotBlank(bo.getDramaTitle()), OceAdvertiserReferralRelation::getDramaTitle, bo.getDramaTitle());
        lqw.like(StringUtils.isNotBlank(bo.getCreateName()), OceAdvertiserReferralRelation::getCreateName, bo.getCreateName());
        lqw.eq(bo.getEndTime() != null, OceAdvertiserReferralRelation::getEndTime, bo.getEndTime());
        if (bo.getDeptId() != null) {
            List<SysDept> deptList = deptMapper.selectListByParentId(bo.getDeptId());
            List<Long> ids = StreamUtils.toList(deptList, SysDept::getDeptId);
            ids.add(bo.getDeptId());
            lqw.in(OceAdvertiserReferralRelation::getDeptId, ids);
        }
        lqw.orderByDesc(OceAdvertiserReferralRelation::getAdvertiserReferralId);
        return lqw;
    }

    /**
     * 新增推广链接-广告主关联
     *
     * @param bo 推广链接-广告主关联
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OceAdvertiserReferralRelationBo bo) {
        Long deptId = LoginHelper.getDeptId();
//        Long userId = LoginHelper.getUserId();
        String username = LoginHelper.getUsername();
        OceAdvertiserReferralRelation add = MapstructUtils.convert(bo, OceAdvertiserReferralRelation.class);
        if(!ObjectUtils.isEmpty(deptId)){
            add.setDeptId(deptId);
        }else{
            add.setDeptId(bo.getDeptId());
        }
        add.setCreateBy(username);
        add.setUpdateBy(username);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            getCacheAdvertiserInfoByReferralLinkId(add.getReferralLinkId());
            bo.setAdvertiserReferralId(add.getAdvertiserReferralId());
            dsdjServeRemoteService.deleteReferralIdListCache(bo.getReferralLinkType());
        }
        return flag;
    }

    /**
     * 修改推广链接-广告主关联
     *
     * @param bo 推广链接-广告主关联
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(OceAdvertiserReferralRelationBo bo) {
//        Long userId = LoginHelper.getUserId();
        String username = LoginHelper.getUsername();
        OceAdvertiserReferralRelation update = MapstructUtils.convert(bo, OceAdvertiserReferralRelation.class);
        update.setUpdateBy(username);
        validEntityBeforeSave(update);
        GetAdvertiserInfo advertiserInfo = null;
        for (JuLiangProperties juLiangProperties : juLiangConfig.getJuLiangConfigList()) {
            MDC.put("appCode", juLiangProperties.getAppCode());
            advertiserInfo = oceanEngineRemoteService.getAdvertiserInfo(Long.valueOf(bo.getThirdAdvertiserId()));
            if (advertiserInfo != null) {
                break;
            }
        }
        if (Objects.nonNull(advertiserInfo)) {
            update.setThirdAdvertiserAppCode(advertiserInfo.getAppCode());
        }
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            String key = "oce:advertiserReferralRelation:" + bo.getReferralLinkId();
            RedisUtils.deleteKeys(key);
            getCacheAdvertiserInfoByReferralLinkId(update.getReferralLinkId());
            dsdjServeRemoteService.deleteReferralIdListCache(bo.getReferralLinkType());
        }
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OceAdvertiserReferralRelation entity) {
        if (Objects.isNull(entity.getAdvertiserReferralId())) {
            OceAdvertiserReferralRelationBo bo = new OceAdvertiserReferralRelationBo();
            bo.setThirdAdvertiserId(entity.getThirdAdvertiserId());
            LambdaQueryWrapper<OceAdvertiserReferralRelation> lqw = buildQueryWrapper(bo);
            OceAdvertiserReferralRelation result = baseMapper.selectOne(lqw);
            if (Objects.nonNull(result)) {
                if (CommonConstants.PULL_STATUS_OFF.equals(result.getPullStatus())) {
                    throw new ServiceException("广告主已经绑定推广链接，请直接开启状态");
                }
                throw new ServiceException("广告主已经绑定其他推广链接，请关闭后再新增");
            }
            OceAdvertiserReferralRelationBo boReferralLinkId = new OceAdvertiserReferralRelationBo();
            boReferralLinkId.setReferralLinkId(entity.getReferralLinkId());
            LambdaQueryWrapper<OceAdvertiserReferralRelation> lqwReferralLinkId = buildQueryWrapper(boReferralLinkId);
            OceAdvertiserReferralRelation resultReferralLinkId = baseMapper.selectOne(lqwReferralLinkId);
            if (Objects.nonNull(resultReferralLinkId)) {
                throw new ServiceException("此推广链接id已经绑定,请更换后重试！");
            }
            int count = oceAdvertiserEverydayCostMapper.selectList(new LambdaQueryWrapper<OceAdvertiserEverydayCost>()
                .eq(OceAdvertiserEverydayCost::getThirdAdvertiserId, entity.getThirdAdvertiserId())
                .eq(OceAdvertiserEverydayCost::getThatdayTimestamp, DateTimeUtil.getTimestampSecond())).size();
            if (count > 0) {
                throw new ServiceException("此推广链接今日已存在消耗或者充值记录，不能绑定推广链接id，请更换重试。");
            }
        } else {
            OceAdvertiserReferralRelation old = baseMapper.selectById(entity.getAdvertiserReferralId());
            Integer pullStatus = entity.getPullStatus();
            if (Objects.equals(pullStatus, CommonConstants.PULL_STATUS_OFF)) {
                int count = oceAdvertiserEverydayCostMapper.selectList(new LambdaQueryWrapper<OceAdvertiserEverydayCost>()
                    .eq(OceAdvertiserEverydayCost::getThirdAdvertiserId, entity.getThirdAdvertiserId())
                    .eq(OceAdvertiserEverydayCost::getThatdayTimestamp, DateTimeUtil.getTimestampSecond())).size();
                if (count > 0) {
                    throw new ServiceException("此推广链接今日已存在消耗或者充值记录，不能绑定推广链接id，请更换重试。");
                }
            }
            if (Objects.nonNull(old)) {
                if (!old.getReferralLinkId().equals(entity.getReferralLinkId())) {
                    int countCost = oceAdvertiserEverydayCostMapper.selectList(new LambdaQueryWrapper<OceAdvertiserEverydayCost>()
                        .eq(OceAdvertiserEverydayCost::getReferralLinkId, entity.getReferralLinkId())
                        .eq(OceAdvertiserEverydayCost::getThatdayTimestamp, DateTimeUtil.getTimestampSecond())).size();
                    if (countCost > 0) {
                        throw new ServiceException("此推广链接今日已存在消耗或者充值记录，不能绑定推广链接id，请更换重试。");
                    }
                }
            }
            long count = baseMapper.selectCount(new LambdaQueryWrapper<OceAdvertiserReferralRelation>()
                .and((wrapper) -> {
                    wrapper.eq(OceAdvertiserReferralRelation::getThirdAdvertiserId, entity.getThirdAdvertiserId())
                        .or().eq(OceAdvertiserReferralRelation::getReferralLinkId, entity.getReferralLinkId());
                })
                .ne(OceAdvertiserReferralRelation::getAdvertiserReferralId, entity.getAdvertiserReferralId())
            );
            if (count > 0) {
                throw new ServiceException("推广链接或广告主已经存在");
            }
        }
    }

    /**
     * 校验并批量删除推广链接-广告主关联信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public OceAdvertiserReferralRelation getCacheAdvertiserInfoByReferralLinkId(Long referralLinkId) {
        String key = GlobalConstants.GLOBAL_REDIS_KEY + "oce:advertiserReferralRelation:" + referralLinkId;
        OceAdvertiserReferralRelation advertiserReferralRelation = RedisUtils.getCacheObject(key);
        if (Objects.nonNull(advertiserReferralRelation)) {
            return advertiserReferralRelation;
        }
        advertiserReferralRelation = baseMapper.getAdvertiserInfoByReferralLinkId(referralLinkId);
        if (Objects.nonNull(advertiserReferralRelation)) {
            RedisUtils.setCacheObject(key, advertiserReferralRelation, Duration.ofMinutes(30L));
        }
        return advertiserReferralRelation;
    }
}
